package com.ruoyi.fantasy.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.huanzhidadi.fantasy.common.constant.Constants;
import com.huanzhidadi.fantasy.common.constant.RedisConstants;
import com.huanzhidadi.fantasy.common.utils.RandomUtils;
import com.ruoyi.fantasy.domain.FantasyCityMapBO;
import com.ruoyi.fantasy.domain.FantasyItemBO;
import com.ruoyi.fantasy.domain.FantasyItemTypeBO;
import com.ruoyi.fantasy.service.FantasyItemLogService;
import com.ruoyi.fantasy.service.FantasyItemService;
import com.ruoyi.fantasy.service.IFantasyItemtypeService;
import com.ruoyi.fantasy.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

@Slf4j
@Component("itemTask")
public class ItemTask {
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private FantasyItemService fantasyItemService;

    @Autowired
    private IFantasyItemtypeService fantasyItemtypeService;

    @Autowired
    private FantasyItemLogService fantasyItemLogService;

    //WorldInit中初始化的城市
    public Map<String, String> cityMaps = new HashMap<>();
    //WorldInit中初始化的道具类型
    public Map<String, String> itemTypes = new HashMap<>();
    public Map<String, FantasyItemBO[]> ranItems = new HashMap<>();

    /**
     * 刷新地面道具
     */
    public void refreshGroundItems() {
        this.cleanGroundItems();
        this.randomItems();
    }

    /**
     * 随机分发道具前先清空前一次随机分发的未拾取的道具
     */
    public void cleanGroundItems() {
        //随机分发道具前先清空前一次随机分发的未拾取的道具
        log.info("清理现有道具开始。");
        //查询出所有者为系统，且只存在一次的记录，也就是系统生成后没有进行过流转的道具
        fantasyItemLogService.deleteOneItemLog();
        // 从redis中取出json串转成实体类数组ranItems
        Map<String, String> ranItemStrMap = redisUtil.hmGet(RedisConstants.FANTASY_ITEM);
        Iterator it = ranItemStrMap.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry<String, String> entry = (Map.Entry)it.next();
            List<FantasyItemBO> fantasyItemBOList = JSONObject.parseArray(entry.getValue(), FantasyItemBO.class);
            FantasyItemBO[] items = new FantasyItemBO[fantasyItemBOList.size()];
            for (int j=0; j<fantasyItemBOList.size(); j++) {
                items[j] = fantasyItemBOList.get(j);
            }
            ranItems.put(entry.getKey(), items);
        }

        if (!ranItems.isEmpty()) {
            //根据当前拥有者清除数据库中的数据
            List<String> itemIdList = new ArrayList<String>();
            //循环前一次随机生成的基于城市的道具数组，每个城市最多存在30个道具
            for (FantasyItemBO[] fantasyItemArray : ranItems.values()) {
                //循环城市地面的所有位置
                for(FantasyItemBO fantasyItemBO : fantasyItemArray) {
                    //本次随机生成的道具列表中仍然属于系统的道具
                    if (fantasyItemBO != null && fantasyItemBO.getOwnerType() == Constants.Item_OWNER_SYSTEM) {
                        itemIdList.add(fantasyItemBO.getItemId());
                    }
                }
            }
            //获取由于系统重启或其他原因造成的历史未被回收的地面道具
            //修改mapper文件中返回值类型从Long到String，解决itemService.removeItemByList(itemIdList);里报Long无法转换为String的异常
            List<String> oldGroundItems = fantasyItemService.getOldGroundItems();
            //追加到待删除列表
            itemIdList.addAll(oldGroundItems);
            //从数据库中删除待删除列表的道具
            fantasyItemService.removeItemByList(itemIdList);
            //清空缓存中本次随机生成的道具列表
            ranItems.clear();
            redisUtil.delValue(RedisConstants.FANTASY_ITEM);
            log.info("清理现有道具结束。{}", ranItems.isEmpty());
        }

    }

    /**
     * @method: randomItem
     * @Description: 随机发送道具到各个地点
     * @Param: []
     * @return: void
     * @creat_user: wang
     * @creat_date: 2018/9/30
     * @creat_time: 15:10
     * @modify1: by wang on 2018/9/30
     **/
    public void randomItems() {

        log.info("随机发送道具开始。");
        cityMaps = redisUtil.hmGet(RedisConstants.FANTASY_CITYMAP_INFO);
        log.info("cityMaps.size() = {}", cityMaps.size());
        itemTypes = redisUtil.hmGet(RedisConstants.FANTASY_ITEM_TYPE);
        log.info("itemTypes.size() = {}", itemTypes.size());
        if (itemTypes.isEmpty()) {
            log.info("itemTypes缓存为空，重新初始化缓存。");
            // itemTypes缓存为空，重新初始化缓存
            fantasyItemtypeService.cacheFantasyItemtypeList();
            itemTypes = redisUtil.hmGet(RedisConstants.FANTASY_ITEM_TYPE);
            log.info("itemTypes.size() = {}", itemTypes.size());
        }

        int count = cityMaps.size();
        //有多少地点就初始化多少个道具
        while (count > 0) {
            count--;
            //随机取一个地图位置
            String fantasyCityMapStr = RandomUtils.getRandomValueFromMap(cityMaps);
            FantasyCityMapBO fantasyCityMapBO = JSONObject.parseObject(fantasyCityMapStr, FantasyCityMapBO.class);
            //随机取一个道具
            String fantasyItemTypeStr = RandomUtils.getRandomValueFromMap(itemTypes);
            FantasyItemTypeBO fantasyItemTypeBO = JSONObject.parseObject(fantasyItemTypeStr, FantasyItemTypeBO.class);

            //创建道具
            FantasyItemBO fantasyItemBO = fantasyItemService.createRandomItem(fantasyItemTypeBO, fantasyCityMapBO);
            //使用数组存储数据，实现在页面的固定格子显示道具。
            //如果当前地点没有初始化过道具，就生成一个新的道具数组
            if(!ranItems.containsKey(fantasyCityMapBO.getId())){
                ranItems.put(fantasyCityMapBO.getId(), new FantasyItemBO[30]);
            }
            //获取该地点上的道具数组
            FantasyItemBO[] items = ranItems.get(fantasyCityMapBO.getId());
            for (int i=0; i<items.length; i++) {
                //循环该地点的道具数组，在第一个为空的格子中生成一个新的道具，跳出循环
                if (items[i] == null) {
                    items[i] = fantasyItemBO;
                    break;
                }
            }
        }
        // 转换为json串保存入redis
        Map<String, String> ranItemStrMap = new HashMap<>();
        Iterator it = ranItems.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry<String, FantasyItemBO[]> entry = (Map.Entry)it.next();
            ranItemStrMap.put(entry.getKey(), JSON.toJSONString(entry.getValue()));
        }
        redisUtil.hmPut(RedisConstants.FANTASY_ITEM, ranItemStrMap);

        log.info("随机发送道具结束。");
    }
}
